package com.nf.db.handler.map;

import com.nf.db.ResultSetHandler;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

import static com.nf.db.RowProcessor.DEFAULT_ROWPROCESSOR;

/**
 * 此类型也可以处理多行结果集，类似于AbstractListHandler，
 * 只不过这里是用Map而不是List
 * Map里面的一个条目代表结果集的一条记录，这一条记录跟AbstractListHandler类似，
 * 也可以有如下几种情况
 * <ul>
 *     <li>Scalar</li>
 *     <li>Array</li>
 *     <li>Map</li>
 *     <li>Bean</li>
 * </ul>
 * <p>
 * 所以此抽象类的子类有如下几个
 * <ul>
 *     <li>ColumnMapHandler</li>
 *     <li>ArrayMapHandler</li>
 *     <li>MapMapHandler</li>
 *     <li>BeanMapHandler</li>
 * </ul>
 * <p>
 * 其通常的用法如下
 * <pre class="code">
 *   ResultSetHandler h = new MapMapHandler("id");
 *   Map found = (Map) sqlExecutor.query("select id, emp_name, salary from employee", h);
 *   Map empMap = (Map) found.get(new Long(1)); // 依据员工的主键值获取一条记录，这条记录仍然是一个Map
 *   String empName = (String) empMap.get("emp_name");
 *   BigDecimal salary = (Integer) empMap.get("salary");
 * </pre>
 * <p>
 */
public abstract class AbstractMapHandler<K, V> implements ResultSetHandler<Map<K, V>> {
    protected String columnName;

    protected AbstractMapHandler(String columnName) {
        this.columnName = columnName;
    }

    @Override
    public Map<K, V> handle(ResultSet rs) throws SQLException {
        Map<K, V> map = createMap();
        while (rs.next()) {
            map.put(createKey(rs), createRow(rs));
        }
        return map;
    }

    protected Map<K, V> createMap() {
        return new HashMap<>();
    }

    protected K createKey(ResultSet rs) throws SQLException {
        return DEFAULT_ROWPROCESSOR.toScalar(rs, columnName);
    }

    protected abstract V createRow(ResultSet rs) throws SQLException;

}
